import React, {
  useContext,
  useState,
  useEffect,
  useRef,
  useMemo,
  useImperativeHandle,
} from 'react';
import { Table, Input, Button, Form, Space, message } from 'antd';
import { FormInstance } from 'antd/lib/form';
import './index.less';
import { TextWidget, getMessage } from '@inbiz/react';

// 生成随机字符串
const random = (): string => {
  const s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';
  let l = s.length;
  let n = '';
  for (let i = 1; i < 20; i++) {
    if (i % 5 || !i) {
      n += s.charAt(Math.floor(Math.random() * l));
    } else {
      n += '-';
    }
  }
  return n;
};

const EditableContext = React.createContext<FormInstance<any> | null>(null);

interface Item {
  Id: string;
  Value: string;
  Text: string;
}

interface EditableRowProps {
  index: number;
}

// 可修改表格组件-行
const EditableRow: React.FC<EditableRowProps> = ({ index, ...props }) => {
  return (
    // <Form form={form} component={false}>
    // <EditableContext.Provider value={form}>
    <tr {...props} />
    // </EditableContext.Provider>
    // </Form>
  );
};

interface EditableCellProps {
  title: React.ReactNode;
  editable: boolean;
  children: React.ReactNode;
  dataIndex: keyof Item;
  record: Item;
  nowKey: string;
  setNowKey: (b: string) => void;
  handleSave: (record: Item) => void;
  changeError: (b: boolean) => void;
}

// 可修改表格组件-列（单元格）
const EditableCell: React.FC<EditableCellProps> = ({
  title,
  editable,
  children,
  dataIndex,
  record,
  nowKey,
  setNowKey,
  handleSave,
  changeError,
  ...restProps
}) => {
  const [editing, setEditing] = useState(false);
  const inputRef = useRef(null);
  const form = useContext(EditableContext)!;

  useEffect(() => {
    if (editing && inputRef.current) {
      let dom: HTMLElement = inputRef.current;
      dom?.focus();
    }
  }, [editing]);

  const toggleEdit = () => {
    setNowKey(record.Id);
    setEditing(true);
    form.setFieldsValue({ [dataIndex]: record[dataIndex] });
  };

  const save = async () => {
    setEditing(false);
    try {
      const values = await form.validateFields();
      handleSave({ ...record, ...values });
      changeError(false);
    } catch (errInfo) {
      console.log('Save failed:', errInfo);
      changeError(true);
    }
  };

  let childNode = children;

  if (editable) {
    childNode =
      editing && nowKey === record.Id ? (
        <Form.Item
          style={{ margin: 0 }}
          name={dataIndex}
          rules={[
            {
              required: true,
              message: `${title}${getMessage('EformStaticList.cannotBeEmpty')}`,
            },
          ]}
        >
          <Input ref={inputRef} onPressEnter={save} onBlur={save} />
        </Form.Item>
      ) : (
        <div
          className="editable-cell-value-wrap"
          id={`cell-${dataIndex}-${record.Id}`}
          style={{ paddingRight: 24 }}
          onClick={toggleEdit}
        >
          {children}
        </div>
      );
  }

  return <td {...restProps}>{childNode}</td>;
};

type EditableTableProps = Parameters<typeof Table>[0];

interface DataType {
  Id: React.Key;
  Value: string;
  Text: string;
}

type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>;

interface IProp {
  gRef: any;
  data: any;
  groupId: string;
  save: Function;
}

// 可修改表格组件
const EditableTable = (props: IProp) => {
  const [dataSource, $dataSource] = useState([]);
  const [selectKeys, $selectKeys] = useState<string[]>([]);
  const [count, $count] = useState(1);
  const [delDisabled, $delDisabled] = useState(true);
  const [groupId, $groupId] = useState<any>(null);
  const [hasError, $hasError] = useState(false);
  const [loading, $loading] = useState(false);
  const [nowKey, $nowKey] = useState(null);

  const [form] = Form.useForm();

  const columns = [
    {
      title: getMessage('EformStaticList.value'),
      dataIndex: 'Value',
      width: '45%',
      editable: true,
    },
    {
      title: getMessage('EformStaticList.text'),
      dataIndex: 'Text',
      width: '45%',
      editable: true,
    },
  ];

  // 暴露提交方法给父组件
  useImperativeHandle(props.gRef, () => ({
    submit: () =>
      new Promise((resolve) => {
        let nowData: any = [...dataSource];
        let record: any = null;
        let data: Array<object> = [];
        // 去掉key，同时判断数据非空
        for (let i = 0; i < nowData.length; i++) {
          if (nowData[i].Value === '' || nowData[i].Text === '') {
            record = nowData[i];
            break;
          }
          data.push({ Value: nowData[i].Value, Text: nowData[i].Text });
        }
        if (!record) {
          let arr: string[] = [];
          let cf: boolean = false;
          // 循环遍历判断是否有重复value值
          for (let i = 0; i < nowData.length; i++) {
            if (arr.indexOf(nowData[i].Value) >= 0) {
              message.error(getMessage('EformStaticList.tips.duplicateRecordsCannotBeAdded'));
              cf = true;
              break;
            }
            arr.push(nowData[i].Value);
          }
          if (!cf) {
            resolve(data);
          }
        } else {
          let type = record.Value === '' ? 'Value' : 'Text';
          document.getElementById(`cell-${type}-${record.Id}`)?.click();
          setTimeout(() => {
            form.validateFields();
          });
        }
      }),
  }));

  // 获取、更新groupId
  useEffect(() => {
    $groupId(props.groupId);
  }, [props.groupId]);

  // 初始化数据添加key
  useEffect(() => {
    let data = props.data;
    // data = data.map(item => ({ ...item, Key: item.Id }))
    $dataSource(data);
  }, [props.data]);

  // 添加一行数据
  const handleAdd = () => {
    const newData: DataType = {
      Id: random(),
      Value: '',
      Text: '',
    };
    $dataSource([...dataSource, newData] as never[]);
    $count(count + 1);
  };

  // 删除选中数据
  const handleDel = () => {
    let data = [...dataSource];
    let keys = [...selectKeys];
    selectKeys.map((i) => {
      data = data.filter((item: any) => item.Id != i);
      keys = keys.filter((item) => item != i);
    });
    $dataSource(data);
    $selectKeys(keys);
    $delDisabled(true);
  };

  // 保存数据
  const handleSaveData = () => {
    let nowData: any = [...dataSource];
    let record: any = null;
    let data: Array<object> = [];
    // 去掉key，同时判断数据非空
    for (let i = 0; i < nowData.length; i++) {
      if (nowData[i].Value === '' || nowData[i].Text === '') {
        record = nowData[i];
        break;
      }
      data.push({ Value: nowData[i].Value, Text: nowData[i].Text });
    }
    if (!record) {
      let arr: string[] = [];
      let cf: boolean = false;
      // 循环遍历判断是否有重复value值
      for (let i = 0; i < nowData.length; i++) {
        if (arr.indexOf(nowData[i].Value) >= 0) {
          message.error(getMessage('EformStaticList.tips.duplicateRecordsCannotBeAdded'));
          cf = true;
          break;
        }
        arr.push(nowData[i].Value);
      }
      if (!cf) {
        let arr = nowData.map((item: any, idx: any) => ({
          columnSort: idx,
          value: item.Value,
          text: item.Text,
        }));
        props.save && props.save(arr);
      }
    } else {
      let type = record.Value === '' ? 'Value' : 'Text';
      document.getElementById(`cell-${type}-${record.Id}`)?.click();
      setTimeout(() => {
        form.validateFields();
      });
    }
  };

  // 修改保存刚编辑表格的数据
  const handleSave = (row: DataType) => {
    const newData: DataType[] = [...dataSource];
    const index = newData.findIndex((item: any) => row.Id === item.Id);
    const item = newData[index];
    newData.splice(index, 1, {
      ...item,
      ...row,
    });
    $dataSource(newData as never);
  };

  // 改变表单验证状态
  const changeError = (b: boolean) => {
    $hasError(b);
  };

  const components = useMemo(() => {
    return {
      body: {
        row: EditableRow,
        cell: EditableCell,
      },
    };
  }, []);

  const columnsed = columns.map((col) => {
    if (!col.editable) {
      return col;
    }
    return {
      ...col,
      onCell: (record: DataType) => ({
        record,
        editable: col.editable,
        dataIndex: col.dataIndex,
        title: col.title,
        nowKey: nowKey,
        setNowKey: (e: any) => $nowKey(e),
        handleSave: handleSave,
        changeError: changeError,
      }),
    };
  });

  return (
    <div className="edit-table-g">
      <Form form={form} component={false}>
        <EditableContext.Provider value={form}>
          <Space>
            <Button
              onClick={handleAdd}
              type="primary"
              disabled={!groupId}
              style={{ marginBottom: 16 }}
            >
              <TextWidget>EformStaticList.add</TextWidget>
            </Button>
            <Button disabled={delDisabled} onClick={handleDel} style={{ marginBottom: 16 }} danger>
              <TextWidget>EformStaticList.delete</TextWidget>
            </Button>
            <Button onClick={handleSaveData} disabled={!groupId} style={{ marginBottom: 16 }}>
              <TextWidget>EformStaticList.save</TextWidget>
            </Button>
          </Space>
          <Table
            loading={loading}
            components={components}
            rowClassName="eform-static-lsit-edit-table"
            bordered
            dataSource={dataSource}
            columns={columnsed as ColumnTypes}
            pagination={false}
            size="middle"
            scroll={{ y: 228 }}
            rowKey="Id"
            rowSelection={{
              selectedRowKeys: selectKeys,
              onChange: (selectedRowKeys) => {
                if (selectedRowKeys.length) {
                  $delDisabled(false);
                  $selectKeys(selectedRowKeys as string[]);
                } else {
                  $delDisabled(true);
                  $selectKeys(selectedRowKeys as string[]);
                }
              },
            }}
          />
        </EditableContext.Provider>
      </Form>
    </div>
  );
};

export default EditableTable;
